﻿using System;
using System.Collections.Generic;
using System.Linq;
using Vallejos.Entidades.Interfaces;
using Vallejos.Entidades.ModeloDeDatos;
using Vallejos.Mensajes;
using Vallejos.Datos.Accesos;


namespace Vallejos.Negocio
{
    public class ProductoBLL : IProducto
    {
        private readonly ProductoDAL _producto;
        private readonly HelperCache _cache;
        private readonly ConcesionariaBLL _concesionaria;
        public ProductoBLL()
        {
            _producto = new ProductoDAL();
            _cache = new HelperCache();
            _concesionaria = new ConcesionariaBLL();
        }

        public List<Marca> LeerMarcas()
        {
            var marcas = _cache.ObtenerLista<Marca>();

            if(marcas == null)
            {
                marcas = _producto.LeerMarcas();
                var localidades = LeerModelos();

                foreach (var marca in marcas)
                    foreach (var localidad in localidades.Where(localidad => localidad.Marca.Id == marca.Id))
                        marca.Modelos.Add(localidad);

                _cache.SetearLista(marcas);
            }
            return marcas;
        }

        public List<Modelo> LeerModelos()
        {
            return _cache.ObtenerLista<Modelo>() ?? _cache.SetearLista(_producto.LeerModelos());
        }

        public void AlmacenarEntidadEnEdicion<T>(T entidad)
        {
            _cache.AlmacenarEntidadEnEdicion(entidad);
        }

        public T RecuperarEntidadEnEdicion<T>()
        {
            return _cache.RecuperarEntidadEnEdicion<T>();
        }

        internal List<Modelo> LeerModelos(int idMarca)
        {
            var modelos =
                LeerModelos().Where(modelo => modelo.Marca.Id == idMarca).ToList();


            return modelos;
        }


        public List<TipoCombustible> LeerTiposCombustible(int idLenguaje)
        {
            return _cache.ObtenerLista<TipoCombustible>() ?? _cache.SetearLista(_producto.LeerTiposCombustible(idLenguaje));
        }

        public List<TipoFinanciacion> LeerTiposFinanciacion(int idLenguaje)
        {
            return _cache.ObtenerLista<TipoFinanciacion>() ?? _cache.SetearLista(_producto.LeerTiposFinanciacion(idLenguaje));
        }

        public List<UsoDeProducto> LeerUsosDeProducto(int idLenguaje)
        {
            return _cache.ObtenerLista<UsoDeProducto>() ?? _cache.SetearLista(_producto.LeerUsosDeProducto(idLenguaje));
        }

        public List<TipoProducto> LeerTiposProducto(int idLenguaje)
        {
            return _cache.ObtenerLista<TipoProducto>() ?? _cache.SetearLista(_producto.LeerTiposProducto(idLenguaje));
        }


        public Producto LeerProducto(int idProducto, int idLenguaje)
        {
            var producto = _producto.LeerProducto(idProducto);
            producto.Marca = LeerMarcas().Single(marca => marca.Id == producto.Marca.Id);
            producto.Modelo = LeerModelos().Single(modelo => modelo.Id == producto.Modelo.Id);
            producto.TipoDeProducto = LeerTiposProducto(idLenguaje).Single(tipo => tipo.idTipo == producto.TipoDeProducto.idTipo);
            producto.Uso = LeerUsosDeProducto(idLenguaje).Single(uso => uso.idUso == producto.Uso.idUso);
            producto.TipoDeCombustible =
                LeerTiposCombustible(idLenguaje).Single(tipo => tipo.idTipo == producto.TipoDeCombustible.idTipo);
            producto.Concesionaria = _concesionaria.LeerConcesionaria(producto.Concesionaria.Id);

            return producto;
        }

        public Producto GuardarProducto(Producto producto)
        {
            return _producto.GuardarProducto(producto);
        }


        public List<Producto> BuscarProductos(Producto producto, int idLenguaje, int desde, int hasta)
        {
            var productos = _producto.BuscarProductos(producto, desde, hasta);
            var tipos = LeerTiposProducto(idLenguaje);
            var usos = LeerUsosDeProducto(idLenguaje);
            var marcas = LeerMarcas();
            var modelos = LeerModelos();

            return productos.Select(prod =>
                                 {
                                     prod.TipoDeProducto =
                                         tipos.Single(tipo => tipo.idTipo == prod.TipoDeProducto.idTipo);
                                     prod.Uso = usos.Single(uso => uso.idUso == prod.Uso.idUso);
                                     prod.Marca = marcas.Single(marca => marca.Id == prod.Marca.Id);
                                     prod.Modelo = modelos.Single(modelo => modelo.Id == prod.Modelo.Id);
                                     return prod;
                                 }).ToList();
        }


        public void RealizarConsulta(Consulta consulta)
        {
            _producto.RealizarConsulta(consulta);
        }

        public List<Consulta> LeerConsultasDeProducto(int idProducto)
        {
            return _producto.LeerConsultasDeProducto(idProducto);
        }

        [Obsolete("Usar LeerProducto(int idProducto, int idLenguaje)")]
        public Producto LeerProducto(int idProducto)
        {
            throw new System.NotImplementedException();
        }
    }
}
